<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Controller\admin;

use App\Model\Admin\Admin;
use App\Model\Admin\AdminRole;
use Hyperf\HttpServer\Annotation\AutoController;
use Psr\Http\Message\ResponseInterface;
use Hyperf\DbConnection\Model\Model;
/**
 * 管理员列表.
 */
#[AutoController]
class AdminController extends Crud
{
    /**
     * 不需要鉴权的方法.
     */
    protected array $noNeedAuth = ['select'];

    /**
     * @var Admin
     */
    protected Model $model;

    /**
     * 构造函数.
     */
    public function __construct()
    {
        $this->model = new Admin();
        parent::__construct();
    }

    /**
     * 浏览.
     */
    public function index(): ResponseInterface
    {
        return $this->render->render('admin/index');
    }

    /**
     * 查询.
     */
    public function select(): ResponseInterface
    {
        [$where, $format, $limit, $field, $order] = $this->selectInput();
        $query = $this->doSelect($where, $field, $order);
        if ($format === 'select') {
            return $this->formatSelect($query->all());
        }
        $paginator = $query->paginate($limit);
        $items = $paginator->items();
        $admin_ids = array_column($items, 'id');
        $roles = AdminRole::whereIn('admin_id', $admin_ids)->get();
        $roles_map = [];
        foreach ($roles as $role) {
            $roles_map[$role['admin_id']][] = $role['role_id'];
        }
        $login_admin_id = admin_id();
        foreach ($items as $index => $item) {
            $admin_id = $item['id'];
            $items[$index]['roles'] = isset($roles_map[$admin_id]) ? implode(',', $roles_map[$admin_id]) : '';
            $items[$index]['show_toolbar'] = $admin_id != $login_admin_id;
        }
        return $this->success($items, 'ok', $paginator->total());
    }

    /**
     * 插入.
     */
    public function insert(): ResponseInterface
    {
        $request = $this->request;
        if ($request->isMethod('post')) {
            $data = $this->insertInput($request);
            unset($data['id']);
            $admin_id = $this->doInsert($data);
            $role_ids = $request->post('roles');
            $role_ids = $role_ids ? explode(',', $role_ids) : [];
            if (! $role_ids) {
                return $this->json(1, '至少选择一个角色组');
            }
            if (! (new common\Auth())->isSuperAdmin() && array_diff($role_ids, (new common\Auth())->getScopeRoleIds())) {
                return $this->json(1, '角色超出权限范围');
            }
            AdminRole::where('admin_id', $admin_id)->delete();
            foreach ($role_ids as $id) {
                $admin_role = new AdminRole();
                $admin_role->admin_id = $admin_id;
                $admin_role->role_id = $id;
                $admin_role->save();
            }
            return $this->json(0, 'ok', ['id' => $admin_id]);
        }
        return $this->render->render('admin/insert');
    }

    /**
     * 更新.
     */
    public function update(): ResponseInterface
    {
        $request = $this->request;
        if ($request->isMethod('post')) {
            [$id, $data] = $this->updateInput($request);
            $admin_id = $request->post('id');
            if (! $admin_id) {
                return $this->json(1, '缺少参数');
            }

            // 不能禁用自己
            if (isset($data['status']) && $data['status'] == 1 && $id == admin_id()) {
                return $this->json(1, '不能禁用自己');
            }

            // 需要更新角色
            $role_ids = $request->post('roles');
            if ($role_ids !== null) {
                if (! $role_ids) {
                    return $this->json(1, '至少选择一个角色组');
                }
                $role_ids = explode(',', $role_ids);

                $is_supper_admin = (new common\Auth())->isSuperAdmin();
                $exist_role_ids = AdminRole::where('admin_id', $admin_id)->pluck('role_id')->toArray();
                $scope_role_ids = (new common\Auth())->getScopeRoleIds();
                if (! $is_supper_admin && ! array_intersect($exist_role_ids, $scope_role_ids)) {
                    return $this->json(1, '无权限更改该记录');
                }
                if (! $is_supper_admin && array_diff($role_ids, $scope_role_ids)) {
                    return $this->json(1, '角色超出权限范围');
                }

                // 删除账户角色
                $delete_ids = array_diff($exist_role_ids, $role_ids);
                AdminRole::whereIn('role_id', $delete_ids)->where('admin_id', $admin_id)->delete();
                // 添加账户角色
                $add_ids = array_diff($role_ids, $exist_role_ids);
                foreach ($add_ids as $role_id) {
                    $admin_role = new AdminRole();
                    $admin_role->admin_id = $admin_id;
                    $admin_role->role_id = $role_id;
                    $admin_role->save();
                }
            }

            $this->doUpdate($id, $data);
            return $this->json(0);
        }

        return $this->render->render('admin/update');
    }

    /**
     * 删除.
     */
    public function delete(): ResponseInterface
    {
        $request = $this->request;
        $primary_key = $this->model->getKeyName();
        $ids = $request->post($primary_key);
        if (! $ids) {
            return $this->json(0);
        }
        $ids = (array) $ids;
        if (in_array(admin_id(), $ids)) {
            return $this->json(1, '不能删除自己');
        }
        if (! (new common\Auth())->isSuperAdmin() && array_diff($ids, (new common\Auth())->getScopeAdminIds())) {
            return $this->json(1, '无数据权限');
        }
        $this->model->whereIn($primary_key, $ids)->each(function (Admin $admin) {
            $admin->delete();
        });
        AdminRole::whereIn('admin_id', $ids)->each(function (AdminRole $admin_role) {
            $admin_role->delete();
        });
        return $this->json(0);
    }

    /**
     * 格式化下拉列表.
     */
    protected function formatSelect(mixed $items): ResponseInterface
    {
        $formatted_items = [];
        foreach ($items as $item) {
            $formatted_items[] = [
                'name' => $item->nickname,
                'value' => $item->id,
            ];
        }
        return $this->json(0, 'ok', $formatted_items);
    }
}
